package com.jay.lang.ref.clazz;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

public class ReferenceQueueCls {
	public static void main(String[] args) throws InterruptedException {
		referenceQueueWithPhantomReference();
		referenceQueueWithWeakReference();
		referenceQueueWithSoftReference();
	}


	public static void referenceQueueWithPhantomReference()
			throws InterruptedException {
		Object referent = new Bean("name", 10);
		ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
		PhantomReference<Object> ref = new PhantomReference<Object>(
				referent, referenceQueue);

		System.out.println("Is enqueued? " + ref.isEnqueued());
		Reference<? extends Object> polled = referenceQueue.poll();
		System.out.println("Any reference? " + polled);

		referent = null;
		System.gc();

		System.out.println("Is enqueued after gc? " + ref.isEnqueued());
		Reference<? extends Object> removed = referenceQueue.remove();
		System.out.println("Any reference after gc? " + removed);
		System.out.println(ref == removed);
		System.out.println("The object refers is " + removed.get());
	}
	
	public static void referenceQueueWithWeakReference()
			throws InterruptedException {
		Object referent = new Bean("name", 10);
		ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
		Reference<Object> ref = new WeakReference<Object>(referent,
				referenceQueue);

		System.out.println("Is enqueued? " + ref.isEnqueued());
		Reference<? extends Object> polled = referenceQueue.poll();
		System.out.println("Any reference? " + polled);

		referent = null;
		System.gc();

		System.out.println("Is enqueued after gc? " + ref.isEnqueued());
		Reference<? extends Object> removed = referenceQueue.remove();
		System.out.println("Any reference after gc? " + removed);
		System.out.println(ref == removed);
		System.out.println("The object refers is " + removed.get());
	}

	public static void referenceQueueWithSoftReference()
			throws InterruptedException {
		Object referent = new Bean("name", 10);
		ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
		Reference<Object> ref = new SoftReference<Object>(referent,
				referenceQueue);

		System.out.println("Is enqueued? " + ref.isEnqueued());
		Reference<? extends Object> polled = referenceQueue.poll();
		System.out.println("Any reference? " + polled);

		referent = null;
		// make oom....
		try {
			double[] d = new double[100000000];

		} catch (Throwable e) {

		}
		System.out.println("Is enqueued after gc? " + ref.isEnqueued());
		Reference<? extends Object> removed = referenceQueue.remove();
		System.out.println("Any reference after gc? " + removed);
		System.out.println(ref == removed);
		System.out.println("The object refers is " + removed.get());
	}
}
